<?php

namespace Core\MVC;

class ViewHandler implements IViewHandler {

    private $viewFolder;
    private $tagFolder;
    private $views;
    private $container;

    public function render($modelMap) {
        // NOTE: instead of local variables, we store some local results in this due to extract call later
        $this->model = $this->resolveViewParams($modelMap->getViewName());
        $this->model = array_merge($this->model, $modelMap->getModel());
        $this->container->materializeReferences($this->model);

        if (!array_key_exists('$view', $this->model)) {
            throw new \Exception("no view file specified for: " . $modelMap->getViewName());
        }

        extract($this->model, EXTR_SKIP); // TODO: some error handling?

        try {
            ob_start();
            require $this->viewFolder . $this->model['$view'] . ".phtml";
            $result = ob_get_contents();
            ob_end_clean();

            echo $result;
        } catch (\Exception $e) {
            ob_end_clean();
            throw $e;
        }
    }

    public function tag($tagName, $tagParams) {
        extract($tagParams, EXTR_SKIP);
        require $this->tagFolder . $tagName . ".phtml";
    }

    private function resolveViewParams($viewName) {
        if (!array_key_exists($viewName, $this->views)) {
            throw new \Exception("Unknown view: " . $viewName);
        }

        $params = $this->views[$viewName];

        if (array_key_exists('$inherit', $params)) {
            $params = array_merge($params, $this->resolveViewParams($params['$inherit']));
        }

        return $params;
    }

    // ACCESS
    public function setViewFolder($viewFolder) {
        $this->viewFolder = $viewFolder;
    }

    public function setTagFolder($tagFolder) {
        $this->tagFolder = $tagFolder;
    }

    public function setViews($views) {
        $this->views = $views;
    }

    public function setContainer($container) {
        $this->container = $container;
    }

}